package com.aaa.ssm.util;
import com.aaa.ssm.entity.OperLog;
import com.aaa.ssm.entity.Patient;
import com.aaa.ssm.entity.SysUser;
import com.aaa.ssm.service.OperLogService;

/*import org.aopalliance.intercept.Joinpoint;*/
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
/**
 * @ fileName:LogRecordUtil
 * @ description:  增强类或者通知类 （日志记录工具类）
 * @ author:zhz
 * @ createTime:2023/10/17 15:30
 * @ version:1.0.0
 */
@Component //不在三层之内  交给spring管理
@Aspect //标识它是一个增强类（切面功能实现类）
public class LogRecordUtil {

    //依赖注入
    @Resource
    private OperLogService operLogService;
    @Resource
    private HttpSession session;
    @Resource
    private HttpServletRequest request;
    /**
     * 用来配置切入点表达式
     * 配置切入点  可以配置多个切入点     * 通配符 第一个任何权限修饰符，任何返回值
     *                                                      第二个* 该包下的任意类
     *                                                      第三个* 该类下的任意方法
     *                                                      (..) 方法0到多个参数
     */
    @Pointcut(value = "execution(* com.aaa.ssm.service.impl.*.add*(..))" +
            "||execution(* com.aaa.ssm.service.impl.*.update*(..))" +
            "||execution(* com.aaa.ssm.service.impl.*.delete*(..))")
    public void pointCutA(){
    }
    // 上面方法相当于 下面这个配置
      /* <aop:pointcut id="pointCutB" expression="execution(* com.aaa.aop.service.impl.*.add*(..))
            ||execution(* com.aaa.aop.service.impl.*.update*(..))
            ||execution(* com.aaa.aop.service.impl.*.delete*(..))
            ||execution(* com.aaa.aop.service.impl..*.insert*(..))"/>*/

    /**
     * 后置通知执行的方法
     * @param joinPoint
     */
   /* <!--配置后置通知   在业务方法执行后要执行的功能-->
            <aop:after-returning method="recordLog" pointcut-ref="pointCutB"></aop:after-returning>*/
    //@Before()
    @AfterReturning(pointcut="pointCutA()")
    //@Around()
    //@AfterThrowing
    //@After()
    public  void  recordLog(JoinPoint joinPoint){
        //实例化对象
        OperLog operLog = new OperLog();
        operLog.setTitle("一期所有模块日志");
        //定义业务类型
        int businessType = 1;
        //获取执行的方法名称
        String methodName = joinPoint.getSignature().getName();
        //判断
        if(methodName.contains("update")){
            businessType=2;
        }else if(methodName.contains("delete")){
            businessType=3;
        }
        //业务类型（0其它 1新增 2修改 3删除）
        operLog.setBusinessType(businessType);
        //反射获取目标对象
        String targetName = joinPoint.getTarget().getClass().getName();
        //targetName= com.aaa.ssm.service.impl.DeptServiceImpl
        operLog.setMethod(targetName+"."+methodName);
        //操作类别（0其它 1后台用户 2手机端用户）
        operLog.setOperatorType(ConstantUtil.OperType.BACK_OPERATE);
        Object userInfo = session.getAttribute("userInfo");
        if (userInfo!=null){
            if (userInfo instanceof SysUser){
                SysUser sysUser = (SysUser)session.getAttribute("userInfo");
                operLog.setOperName(sysUser.getUserName());
            }

            if(userInfo instanceof Patient) {
                String userName = ((Patient) session.getAttribute("userInfo")).getUserName();
                operLog.setOperName(userName);
            }
        }

        operLog.setDeptName("开发部11");
        //获取url
        StringBuffer requestURL = request.getRequestURL();
        //请求URL
        operLog.setOperUrl(requestURL.toString());
        //获取IP
        String remoteAddr = request.getRemoteAddr();
        //主机地址
        operLog.setOperIp(remoteAddr);
        //操作点
        operLog.setOperLocation("郑州");
        //获取参数
        Object[] args = joinPoint.getArgs();
        if(args!=null&&args.length>0){
            //操作参数
            operLog.setOperParam(args[0].getClass().getName());
        }
        //操作状态（0正常 1异常）
        operLog.setStatus(ConstantUtil.LogRecordStatus.SUCCESS);
        operLog.setErrorMsg(null);
        //dao层已经使用now() 获取当前时间了
        //operLog.setOperTime(new Date());
        operLogService.add(operLog);
    }
}

